package com.yuanheng100.ems4j.service;

import com.alibaba.fastjson.JSON;
import com.yuanheng100.ems4j.api.IEmailService;
import com.yuanheng100.ems4j.common.constant.MessageStatus;
import com.yuanheng100.ems4j.mapper.Ems4jEmailMapper;
import com.yuanheng100.ems4j.model.Ems4jEmail;
import com.yuanheng100.ems4j.model.Ems4jPage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by jlqian on 2017/1/18.
 */
@Service
public class EmailServiceImpl implements IEmailService, DisposableBean
{
    private static Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class);

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private Ems4jEmailMapper ems4jEmailMapper;

    private Integer consumerThread = 2;

    public void setConsumerThread(Integer consumerThread)
    {
        this.consumerThread = consumerThread;
    }

    private LinkedBlockingQueue<Ems4jEmail> emailQueue = new LinkedBlockingQueue<Ems4jEmail>();

    private ScheduledExecutorService scheduledExecutorService = null;

    @PostConstruct
    public void init()
    {

        scheduledExecutorService = Executors.newScheduledThreadPool(consumerThread);
        for (int i = 0; i < consumerThread; i++)
        {
            scheduledExecutorService.schedule(new EmailSender(i), 5L, TimeUnit.SECONDS);
        }
    }

    class EmailSender implements Runnable
    {

        private Integer thread = 0;

        EmailSender(Integer thread)
        {
            this.thread = thread;
        }

        @Override
        public void run()
        {
            JavaMailSenderImpl javaMailSender = (JavaMailSenderImpl) mailSender;

            for (; ; )
            {
                try
                {
                    Ems4jEmail ems4jEmail = emailQueue.take();
                    logger.debug("EmailSender-Thread-{}获取邮件，邮件：{}", thread, JSON.toJSONString(ems4jEmail));
                    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
                    try
                    {
                        mimeMessage.setFrom(new InternetAddress(javaMailSender.getUsername(), ems4jEmail.getFromName()));
                        mimeMessage.setRecipients(Message.RecipientType.TO, new InternetAddress(ems4jEmail.getReceiver(), ems4jEmail.getToName()).toString());
                        mimeMessage.setSubject(ems4jEmail.getEmailSubject());
                        mimeMessage.setText(ems4jEmail.getContent());
                        try
                        {
                            mailSender.send(mimeMessage);
                            ems4jEmail.setResult(MessageStatus.SUCCESS.getCode());
                            logger.info("邮件发送成功{}", JSON.toJSONString(ems4jEmail));
                        } catch (MailException e)
                        {
                            logger.error("邮件发送失败！", e);
                            ems4jEmail.setResult(MessageStatus.FAILURE.getCode());
                        }
                        ems4jEmailMapper.updateByPrimaryKey(ems4jEmail);

                    } catch (Exception e)
                    {
                        logger.error("邮件创建失败", e);
                    }

                } catch (InterruptedException e)
                {
                    if(isOff){
                        return;
                    }
                    logger.error("获取Ems4jEmail失败", e);
                }
            }
        }
    }


    @Override
    public int sendEmail(String content, String receiver, String fromName, String toName, String subject)
    {
        JavaMailSenderImpl javaMailSender = (JavaMailSenderImpl) mailSender;

        //持久化
        Ems4jEmail ems4jEmail = new Ems4jEmail();
        ems4jEmail.setContent(content);
        ems4jEmail.setFromName(fromName);
        ems4jEmail.setSender(javaMailSender.getUsername());
        ems4jEmail.setEmailSubject(subject);
        ems4jEmail.setReceiver(receiver);
        ems4jEmail.setToName(toName);
        ems4jEmail.setSendTime(new Date());
        ems4jEmail.setResult(MessageStatus.SENDING.getCode());
        int result = 0;
        try
        {
            emailQueue.put(ems4jEmail);
            result = ems4jEmailMapper.insert(ems4jEmail);
        } catch (InterruptedException e)
        {
            logger.error("邮件放至队列失败", e);
        }
        return result;
    }

    @Override
    public void getPage(Ems4jPage<Ems4jEmail> page, Map<String, Object> conditions)
    {
        //查询总数
        Long total = ems4jEmailMapper.selectCountByCondition(conditions);
        page.setTotalCount(total);

        //查询结果
        List<Ems4jEmail> list = ems4jEmailMapper.selectListByCondition(conditions, page);

        page.setResult(list);
    }

    private boolean isOff = false;

    @Override
    public void destroy() throws Exception
    {
        isOff = true;
        scheduledExecutorService.shutdownNow();
    }

}
